package com.xyq.common.sucurity.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.xyq.common.core.domain.Result;
import com.xyq.common.core.enums.ResultCode;
import com.xyq.common.core.exception.ServiceException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.Collection;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

   // 捕获请求方法不支持的异常
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)  // 加上Request请求 , 方便打印日志
    public Result<?> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e ,
                                                            HttpServletRequest request) {
//         当出现 请求方法不支持异常 , 返回 Result: Error
        // 例如 接口 是post方法 , 但请求是get
        log.error("请求地址{} 不支持{}请求",request.getRequestURI() , e.getMethod());
        return Result.fail(ResultCode.ERROR);
        
    }
    // 处理service异常
    @ExceptionHandler(ServiceException.class)
    public Result<?> ServiceException(ServiceException e , HttpServletRequest request){
//
        ResultCode resultCode = e.getResultCode() ;
        String requestURI = request.getRequestURI();
        log.error("url:{}发生异常{} ",requestURI,e.getMessage() ,e);
        return Result.fail(resultCode);
    }

    // 处理运行时异常
    @ExceptionHandler(RuntimeException.class)
    public Result<?> runtimeException(RuntimeException e , HttpServletRequest request){
//        处理运行时的异常
        log.error("请求地址{} ,发生运行时异常{} , {}",request.getRequestURI(),e.getMessage() , e);
        return Result.fail(ResultCode.ERROR);
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class )
    public Result<?> MaxUploadSizeExceededException(RuntimeException e , HttpServletRequest request){
//        处理运行时的异常
        log.error("上传文件过大",request.getRequestURI(),e.getMessage());
        return Result.fail(ResultCode.ERROR);
    }

    // 处理异常情况
    @ExceptionHandler(Exception.class)
    public Result<?> handleException(Exception e , HttpServletRequest request){
        log.error("请求地址{} ,发生异常{}",request.getRequestURI(),e.getMessage());
        return Result.fail(ResultCode.ERROR);
    }

    // 处理参数异常问题
    @ExceptionHandler()
    public Result<?> handleException(BindException e){
        log.error(e.getMessage());
        // 把 参数验证的所有有问题的参数的 message提取处理 fail返回给前端
        String message = join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, " , ");
        return Result.fail(ResultCode.FAILED_PARAMS_VALIDATE.code , message);
    }
    // 提取所有的message
    private <E> String join(Collection<E> collection, Function<E, String>
            function, CharSequence delimiter) {
        if (CollUtil.isEmpty(collection)) {
            return StrUtil.EMPTY;
        }
        return
                collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
    }

}
